package utils;

import java.util.*;

/**
 * 环形队列
 */
public class CircularQueue {
    private int queueNum;
    private int timer;
    private int currentIndex;
    private Set<Task> [] queue;
    private Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    public CircularQueue(int queueNum, int timer) {
        this.queueNum = queueNum;
        this.timer = timer;
        this.queue = new HashSet[queueNum];
    }

    /**
     * 增加任务
     * @param task
     */
    public void addTask(Task task) {
        if (task == null) return;
        int taskId = task.getId();
        int currentIndex = this.currentIndex - timer < 0 ? this.queueNum - 1 :this.currentIndex - timer ;
        if (map.containsKey(taskId)) {
            int index = map.get(taskId);
            queue[index].remove(task);
            map.remove(taskId);
        }
        if (queue[currentIndex] == null) {
            queue[currentIndex] = new HashSet<Task>();
        }
        this.queue[currentIndex].add(task);
    }

    /**
     *
     */
    public void excute() {
        if (currentIndex > queueNum) {
            currentIndex = 0;
        }
        System.out.println(currentIndex);
        HashSet<Task> set = (HashSet<Task>)queue[currentIndex];
        if (set != null) {
            Iterator<Task> iterator = set.iterator();
            while (iterator.hasNext()) {
                Task task = iterator.next();
                task.handle();
                iterator.remove();
            }
        }
        currentIndex += 1;
    }

    public static void main(String [] args) {
        CircularQueue circularQueue = new CircularQueue(10,1);
        Task<Order> task = new Task<Order>(new Order("订单"), new OrderTaskHandle());
        circularQueue.addTask(task);
        circularQueue.excute();
        //new Producer(circularQueue).run();
        new Consumer(circularQueue).run();
    }
}

class Producer implements Runnable {
    private CircularQueue circularQueue;

    public Producer(CircularQueue circularQueue) {
        this.circularQueue = circularQueue;
    }
    @Override
    public void run() {
        Task<Order> task = new Task<Order>(new Order("订单"), new OrderTaskHandle());
        circularQueue.addTask(task);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer implements Runnable {
    private CircularQueue circularQueue;

    public Consumer(CircularQueue circularQueue) {
        this.circularQueue = circularQueue;
    }
    @Override
    public void run() {
        circularQueue.excute();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Task<T> {
    //任务ID
    private int id;
    //任务数据
    private T data;
    //任务处理逻辑
    private TaskHandle taskHandle;

    private static int nextId = 1;
    public Task(T data, TaskHandle taskHandle) {
        this.id = nextId++;
        this.data =data;
        this.taskHandle = taskHandle;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public TaskHandle getTaskHandle() {
        return taskHandle;
    }

    public void setTaskHandle(TaskHandle taskHandle) {
        this.taskHandle = taskHandle;
    }

    public void handle() {
        this.taskHandle.handle(this);
    }
}

interface TaskHandle {
    void handle(Task task);
}

class OrderTaskHandle implements TaskHandle {

    @Override
    public void handle(Task task) {
        System.out.println("执行处理:"+task.getData().toString());
    }
}

class Order {
    private int id;
    private String name;
    private static int nextId = 1;
    public Order(String name) {
        this.id = nextId++;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", name=" + name +
                '}';
    }
}